原文連結:Working with Structured Data Objects
由於內容較多,今天再介紹一天structure,主要會說明structure與SQL的聯合運作,以及join的使用。
只有在 structure 欄位的數量和型別與 FIELDS
中指定的欄位相對應時,SELECT
語句的 INTO
才能正常運作。可以分成以下三種方式撈取資料至structure:
如下,假設structure中只包含三個欄位()的值,FIELDS
中也須按照順序指定相應欄位。如果有欄位對不上將產生error。
DATA connection TYPE st_connection."connection包含了airport_from_id, airport_to_id, carrier_name三個值對應的欄位"
SELECT SINGLE
FROM /DMO/I_Connection
FIELDS DepartureAirport, DestinationAirport, \_Airline-Name
WHERE ...
INTO @connection.
另外,也可直接將structure型別設為所搜尋的原始資料表,FIELDS
則可直接提取該表所有欄位。
DATA connection TYPE /DMO/I_Connection."直接把原始資料表作為connection的型別"
SELECT SINGLE
FROM /DMO/I_Connection
FIELDS * "選取所有欄位
WHERE ...
INTO @connection.
第二個做法的好處是當原始表格或CDS view欄位變動,不須額外改寫structure,但缺點為會額外撈取到前述三個欄位外的多餘資料。
註:資料庫表格在ABAP中亦可直接作為gobal structure型別來建立structure。
註二:效能上會建議僅在欄位少或確實需要大部分欄位時,採用第二種方法。
使用 INTO CORRESPONDING FIELDS
來達到欄位自動對應,並且可僅截取所需欄位,但structure欄位名稱需要與原始資料表的一致。與稍早提及的CORRESPONDING #( )
效果相同。
DATA connection TYPE st_connection.
"connection包含了DepartureAirport, DestinationAirport, \_Airline-Name三個欄位(名稱與原始表格一致)"
SELECT SINGLE
FROM /DMO/I_Connection
FIELDS * "選取所有欄位
WHERE ...
INTO CORRESPONDING FIELDS OF @connection. "自動對應欄位
由於使用INTO CORRESPONDING FIELDS
需要有一致的命名,當structure與撈取欄位命名不一致,可以為撈取欄位加上別名,系統將會透過別名與structure作對應。
DATA connection TYPE st_connection_short.
"connection包含了airport_from_id, airport_to_id, carrier_name三個欄位"
SELECT SINGLE
FROM /DMO/I_Connection
FIELDS DepartureAirport AS airport_from_id, "建立別名"
\_Airline-Name AS carrier_name "建立別名"
WHERE ...
INTO CORRESPONDING FIELDS OF @connection."存入撈取的兩個欄位
如果要避免欄位對應產生error,也能用一個簡單的方式:當FIELD
撈完資料再用INTO
自動生成對應structure,無須擔心欄位不一致的問題。
SELECT SINGLE
FROM /DMO/I_Connection
FIELDS DepartureAirport,
DestinationAirport AS ArrivalAirport, "建立別名(可選)"
\_Airline-Name AS AirlineName "建立別名(強制)"
WHERE ...
INTO @DATA(connection_inline). "行內宣告structure,欄位依序為DepartureAirport,ArrivalAirport,AirlineName
如果有為撈取的資料建立別名,structure生成時也會以別名為主。如果是一般欄位,別名是可選的,如DestinationAirport
;但如果欄位為表達式,則必需添加別名,如\_Airline-Name
。
當要從關聯是資料表抓資料時,難免會有跨表格的操作,先前有提及使用CDS View來執行這類任務,但如果沒有可代表目標關聯的CDS View,可以使用SQL joins抓取多個具關連的資料表。
以上圖的航班表格為例,airport_from_id
欄位存放了機場的三碼代號,欲在同一個SELECT
指令中從另一張AIRPORT
表格撈出相對應的機場詳細名稱,這時可以使用join同時撈取/DMO/CONNECTION
,/DMO/AIRPORT
兩張表。
一個join中包含了以下三部分:
資料來源:
指要拿來聯接的資料表或視圖,一個join將連結左側與右側的資料來源。例如程式碼中會分別位於左右側的/DMO/CONNECTION
及/DMO/AIRPORT
資料表。
join條件:
join會將位於右側的對應資料值,附屬在左側的對應資料之下,舉例而言,上圖左表的CLIENT 結合AIRPORT_ID欄位後可在右表中被對應識別至特定列,其join條件寫法如下:
/DMO/CONNECTION~CLIENT = /DMO/AIRPORT~CLIENT
AND
/DMO/CONNECTION~AIRPORT_FROM_ID = /DMO/AIRPORT~AIRPORT_ID
INNER JOIN
, LEFT OUTER JOIN
以及 RIGHT OUTER JOIN
. 目前最常見的join類型是LEFT OUTER JOIN
。SELECT SINGLE
"join類型與join條件"
FROM /dmo/connection AS c
LEFT OUTER JOIN /dmo/airport AS f
ON c~airport_from_id = f~airport_id
FIELDS c~carrier_id, c~connection_id,
c~airport_from_id,c~airport_to_id,
f~name AS airport_from_name "從右側的資料來源讀取機場名稱"
WHERE c~carrid = 'LH'
AND c~connection ='0400'
INTO @DATA(connection_join).
上例中,join類型為關鍵字LEFT OUTER JOIN
,LEFT OUTER JOIN
左側資料來源為/dmo/connection
,右側則是/dmo/airport
,並分別以別名c
與f
代稱。
除非資料來源在join中出現多次,否則資料來源的別名是可選的。
join條件前置關鍵字為ON
,並用~
符號連結別名與指定欄位。
SELECT SINGLE
"第一個join類型與join條件"
FROM ( /dmo/connection AS c
LEFT OUTER JOIN /dmo/airport AS f
ON c~airport_from_id = f~airport_id )
LEFT OUTER JOIN /dmo/airport AS t
ON c~airport_from_id = t~airport_id
FIELDS c~carrier_id, c~connection_id,
c~airport_from_id,c~airport_to_id,
f~name AS airport_from_name, "讀取出發機場名稱"
t~name AS airport_to_name "讀取抵達機場名稱"
WHERE c~carrid = 'LH'
AND c~connection ='0400'
INTO @DATA(connection_join).
在範例二不只撈取出發機場,還要撈抵達機場,因此在join上需要使用巢狀寫法,在FROM
後緊接()
先連結第一張表,使用f
與t
分別作為出發機場與抵達機場的別名以區分(即使撈的來源是同一張表/dmo/airport
)。
在FIELD
中分別用別名airport_from_name
and airport_to_name
來作為出發/抵達機場的欄位名稱。
介紹完structure與SQL結合運用的方式後,明天緊接著來介紹Complex Internal Tables!